#pragma once
#include <string>

const std::string blank_space_step = " ";
const std::string protocol_sep = "\n";

// 编码
std::string Encode(std::string context)
{
    // "len"\n"x op y"\nXXXXXX
    std::string package=std::to_string(context.size());
    package+=protocol_sep;
    package+=context;
    package+=protocol_sep;
    return package;
}
// 解码
bool Decode(std::string *context, std::string package)
{
    std::size_t pos=package.find(protocol_sep);
    if(pos==std::string::npos)
        return false;
    std::string part_len=package.substr(0,pos);
    int len=std::stoi(part_len);
    int total_len=part_len.size()+len+2;
    if(package.size()<total_len)
        return false;
    *context=package.substr(pos+1,len);
    package.erase(0,total_len);
    return true;
}

class Request
{
public:
    Request(int data1, int data2, char op)
        : x(data1), y(data2), op(op)
    {
    }

    Request()
    {}
    ~Request()
    {
    }

public:
    bool Serialize(std::string *out)
    {
        // struct ->string "x op y"
        std::string s = std::to_string(x);
        s += blank_space_step;
        s += op;
        s += blank_space_step;
        s += std::to_string(y);
        *out = s;
        return true;
    }
    bool Deserialize(std::string &in)
    {
        // "x op y" ->"x" "op" "y"
        std::size_t left = in.find(blank_space_step);
        if (left == std::string::npos)
            return false;
        std::string part_x = in.substr(0, left);

        std::size_t right = in.rfind(blank_space_step);
        if (right == std::string::npos)
            return false;
        std::string part_y = in.substr(right + 1);

        if (left + 2 != right)
        {
            return false;
        }
        op = in[left + 1];
        x = std::stoi(part_x);
        y = std::stoi(part_y);
        return true;
    }

public:
    int x;
    int y;
    char op;
};

class Response
{
public:
    Response(int result, int code)
        : result_(result), code_(code)
    {
    }
    Response()
    {}
    ~Response()
    {
    }

public:
    bool Serialize(std::string *out)
    {
        // struct ->string "result_ code_"
        std::string s = std::to_string(result_);
        s += blank_space_step;
        s += std::to_string(code_);
        *out = s;
        return true;
    }

    bool Deserialize(std::string &in)
    {
        // "result" "code"
        int pos = in.find(blank_space_step);
        std::string left = in.substr(0, pos);
        std::string right = in.substr(pos + 1);
        result_ = std::stoi(left);
        code_ = std::stoi(right);
        return true;
    }

public:
    int result_;
    int code_;
};